﻿{%- if HasDescription -%}
/** {{ Description }} */
{%- endif -%}
{% if ExportTypes %}export {% endif %}class {{ ClassName }}{{ Inheritance }} {
{%- for property in Properties -%}
{%-     if property.HasDescription -%}
    /** {{ property.Description }} */
{%-     endif -%}
    {% if property.IsReadOnly %}readonly {% endif %}{{ property.PropertyName }} = {% if property.IsArray %}ko.observableArray<{{ property.ArrayItemType }}>({% if property.HasDefaultValue %}{{ property.DefaultValue }}{% endif %}){% else %}ko.observable<{{ property.Type }}{{ property.TypePostfix }}>({% if property.HasDefaultValue %}{{ property.DefaultValue }}{% endif %}){% endif %};
{%- endfor -%}

{%- if HasDiscriminator -%}

    protected _discriminator: string;
{%- endif -%}

{%- if HasBaseDiscriminator -%}
    constructor() {
{%-     if HasInheritance -%}
        super();
{%-     endif -%}
        this._discriminator = "{{ DiscriminatorName }}";
    }
{%- endif -%}

    init(data?: any{% if HandleReferences %}, _mappings?: any{% endif %}) {
{%- if HasInheritance -%}
        super.init(data);
{%- endif -%}
        if (data !== undefined) {
{%- for property in Properties -%}
            var {{ property.PropertyName }}_: any;
            {{ property.ConvertToClassCode | tab }}
            this.{{ property.PropertyName }}({{ property.PropertyName }}_);

{%- endfor -%}
        }
    }

    static fromJS(data: any{% if HandleReferences %}, _mappings?: any{% endif %}): {{ ClassName }}{% if HandleReferences %} | null{% endif %} {
{%- if HandleReferences -%}
{%-   if HasBaseDiscriminator -%}
{%-     for derivedClass in DerivedClasses -%}
        if (data["{{ BaseDiscriminator }}"] === "{{ derivedClass.Discriminator }}")
{%-       if derivedClass.IsAbstract -%}
            throw new Error("The abstract class '{{ derivedClass.ClassName }}' cannot be instantiated.");
{%-       else -%}
            return createInstance<{{ derivedClass.ClassName }}>(data, _mappings, {{ derivedClass.ClassName }});
{%-       endif -%}
{%-     endfor -%}
{%-   endif -%}
{%-   if IsAbstract -%}
        throw new Error("The abstract class '{{ ClassName }}' cannot be instantiated.");
{%-   else -%}
        return createInstance<{{ ClassName }}>(data, _mappings, {{ ClassName }});
{%-   endif -%}
{%- else -%}
{%-   if HasBaseDiscriminator -%}
{%-     for derivedClass in DerivedClasses -%}
        if (data["{{ BaseDiscriminator }}"] === "{{ derivedClass.Discriminator }}") {
{%-       if derivedClass.IsAbstract -%}
            throw new Error("The abstract class '{{ derivedClass.ClassName }}' cannot be instantiated.");
{%-       else -%}
            let result = new {{ derivedClass.ClassName }}();
            result.init(data);
            return result;
{%-       endif -%}
        }
{%-     endfor -%}
{%-   endif -%}
{%-     if IsAbstract -%}
        throw new Error("The abstract class '{{ ClassName }}' cannot be instantiated.");
{%-     else -%}
        let result = new {{ ClassName }}();
        result.init(data);
        return result;
{%-     endif -%}
{%- endif -%}
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
{%- if HasDiscriminator -%}
        data["{{ BaseDiscriminator }}"] = this._discriminator;
{%- endif -%}
{%- for property in Properties -%}
        let {{ property.PropertyName }}_: any = this.{{ property.PropertyName }}();
        {{ property.ConvertToJavaScriptCode | tab }}

{%- endfor -%}
{%- if HasInheritance -%}
        super.toJSON(data);
{%- endif -%}
        return data;
    }
{%- if GenerateCloneMethod -%}

    clone() {
        const json = this.toJSON();
        let result = new {{ ClassName }}();
        result.init(json);
        return result;
    }
{%- endif -%}
}